﻿using AppSocketModel;
using AppSocketService.Account;
using AppSocketService.Vehicle;
using BCGPSCommon; 
using BCGPSMongoData;
using MongoDB.Driver;
using MongoDB.Driver.GeoJsonObjectModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; 

namespace AppSocketService.Fence
{
    public class FencePersonService : ServiceBase, IFencePersonService
    {
        private readonly MongoDBCommand<FenceDto> mongoDBCommand = new MongoDBCommand<FenceDto>("Fence");
        private readonly AccountDto CurrentAccount;
        private readonly GCJ02_WGS84_TransTools gCJ02_WGS84_TransTools = new GCJ02_WGS84_TransTools ();
        private readonly IVehiclePersonService vehiclePersonService;

        public FencePersonService(IClaimsAccessor claimsAccesso, IAccountPersonService accountPersonService,IVehiclePersonService vehiclePersonService):base(claimsAccesso)
        {
            CurrentAccount = accountPersonService.GetCurrentAccount();
            this.vehiclePersonService = vehiclePersonService;
        }
        public FencePersonService()
        {

        }


        public FenceDto AddNew(FenceRequestDto fenceRequestDto)
        {
            if (fenceRequestDto.CoordinateList.Count < 4)
                throw new ArgumentException("围栏不能小于4个点!");

            if (fenceRequestDto.CoordinateList[0].lat != fenceRequestDto.CoordinateList[fenceRequestDto.CoordinateList.Count - 1].lat
                || fenceRequestDto.CoordinateList[0].lng != fenceRequestDto.CoordinateList[fenceRequestDto.CoordinateList.Count - 1].lng)
                throw new ArgumentException("围栏第一个点必须和最后一个点重合!");

            foreach (var item in fenceRequestDto.CoordinateList)
            { 
                LocateInfo info;
                switch (fenceRequestDto.GpsMapType)
                {
                    case GpsMapType.GDMAP:
                        info = gCJ02_WGS84_TransTools.gcj02_To_Wgs84(item.lat, item.lng);
                        item.lat = info.Latitude;
                        item.lng = info.longitude;
                        break;
                    case GpsMapType.BAIDUMAP:
                        info = gCJ02_WGS84_TransTools.bd09_To_Gps84(item.lat, item.lng);
                        item.lat = info.Latitude;
                        item.lng = info.longitude;
                        break;
                }
            }


            var fenceDto = fenceRequestDto.As<FenceDto>();

             
            fenceDto.Id = Guid.NewGuid().ToString();
            fenceDto.CreateDateTime = DateTime.UtcNow;
            fenceDto.UpdateAccountCode = CurrentAccount.AccountCode;
            fenceDto.UpdateAccountRole = CurrentAccount.AccountRoleStr;

            if (CurrentAccount.CompanyId > 0)
            {
                fenceDto.CompanyId = CurrentAccount.CompanyId;
            }
            else
            {
                fenceDto.CompanyId = 0;
                fenceDto.AccountId = CurrentAccount.AccountId;
            }

            mongoDBCommand.InsertDocumentAsync(fenceDto).GetAwaiter().GetResult();
            return fenceDto;
        }

        public void DeleteAll()
        {
            if (CurrentAccount.CompanyId > 0)
                throw new Exception("企业下的个人账户没有删除全部设备围栏设置的权限!");


            var list = vehiclePersonService.GetVehicleList();
            foreach (var item in list)
            {
                DeleteAll(item.IMEI);
            } 
        }

        public long DeleteAll(string IMEI)
        {
            if(CurrentAccount.CompanyId>0)
                return  mongoDBCommand.DeleteDocumentsAsync(s => s.CompanyId ==CurrentAccount.CompanyId && s.IMEI == IMEI).GetAwaiter().GetResult().DeletedCount;
            else
                return mongoDBCommand.DeleteDocumentsAsync(s => s.CompanyId == 0 && s.AccountId == CurrentAccount.AccountId && s.IMEI == IMEI).GetAwaiter().GetResult().DeletedCount;
        }
        public long Delete(string Id)
        {
            return mongoDBCommand.DeleteDocumentAsync(s => s.Id == Id).GetAwaiter().GetResult().DeletedCount;
        }

        public List<FenceDto> GetAll(GpsMapType gpsMapType,string IMEI)
        {
            List<FenceDto> list;
            if(CurrentAccount.CompanyId>0) 
                list = mongoDBCommand.SelectDocumentsAsync(s =>s.CompanyId== CurrentAccount.CompanyId && s.IMEI == IMEI).GetAwaiter().GetResult().OrderBy(s => s.FenceNumber).ToList();
            else
                list = mongoDBCommand.SelectDocumentsAsync(s => s.CompanyId == 0 && s.AccountId == CurrentAccount.AccountId && s.IMEI == IMEI).GetAwaiter().GetResult().OrderBy(s => s.FenceNumber).ToList();

            foreach (var ttt in list)
            {
                foreach (var item in ttt.CoordinateList)
                {
                    LocateInfo info;
                    switch (gpsMapType)
                    { 
                        case GpsMapType.GDMAP:
                            info = gCJ02_WGS84_TransTools.wgs84_To_Gcj02(item.lat, item.lng);
                            item.lat = info.Latitude;
                            item.lng = info.longitude;
                            break;
                        case GpsMapType.BAIDUMAP:
                            info = gCJ02_WGS84_TransTools.wgs84_To_Bd09(item.lat, item.lng);
                            item.lat = info.Latitude;
                            item.lng = info.longitude;
                            break; 
                    }
                }
            }
            return list;
        }

        public FenceDto IntoFenceAlarm(int companyId, string accountId, string IMEI, double lng, double lat)
        {
            string InAlarmStr = string.Empty;

            if (companyId > 0)
                InAlarmStr = "{ IMEI:\"" + IMEI + "\",CompanyId:" + companyId + " ,IsEnable: true,AlarmType: 0, Polygon: { $geoIntersects: { $geometry: { type : \"Point\", coordinates : [" + lng + "," + lat + "] }}}} ";
            else
                InAlarmStr = "{ IMEI:\"" + IMEI + "\",CompanyId:0,AccountId:\"" + accountId + "\" ,IsEnable: true,AlarmType: 0, Polygon: { $geoIntersects: { $geometry: { type : \"Point\", coordinates : [" + lng + "," + lat + "] }}}} ";

            return mongoDBCommand.SelectDocumentAsync(InAlarmStr).GetAwaiter().GetResult();
        }

        public bool OutFenceAlarm(int companyId, string accountId, string IMEI, double lng, double lat)
        {
            FenceDto dto;
            if (companyId > 0)
                dto = mongoDBCommand.SelectDocumentAsync(s => s.CompanyId == companyId && s.IMEI == IMEI && s.IsEnable == true && s.FenceAlarmType == FenceAlarmType.OUT).GetAwaiter().GetResult();
            else
                dto = mongoDBCommand.SelectDocumentAsync(s => s.CompanyId == 0 && s.AccountId == accountId && s.IMEI == IMEI && s.IsEnable == true && s.FenceAlarmType == FenceAlarmType.OUT).GetAwaiter().GetResult();
            if (dto == null)
                return false; //没有设置出的围栏

            string OutAlarmStr = string.Empty;

            if (companyId > 0)
                OutAlarmStr = "{ IMEI:\"" + IMEI + "\",CompanyId:" + companyId + " ,IsEnable: true,AlarmType: 1, Polygon: { $geoIntersects: { $geometry: { type : \"Point\", coordinates : [" + lng + "," + lat + "] }}}} ";
            else
                OutAlarmStr = "{ IMEI:\"" + IMEI + "\",CompanyId:0,AccountId:\"" + accountId + "\" ,IsEnable: true,AlarmType: 1, Polygon: { $geoIntersects: { $geometry: { type : \"Point\", coordinates : [" + lng + "," + lat + "] }}}} ";

            var listOutAreaAlarm = mongoDBCommand.SelectDocumentsAsync(OutAlarmStr).GetAwaiter().GetResult();
            if (listOutAreaAlarm == null || listOutAreaAlarm.Count <= 0)
            {
                return true;
            }
            return false;
        }
        public FenceDto Update(GpsMapType gpsMapType, FenceDto fenceDto )
        {

            foreach (var item in fenceDto.CoordinateList)
            {
                LocateInfo info;
                switch (gpsMapType)
                {
                    case GpsMapType.GDMAP:
                        info = gCJ02_WGS84_TransTools.gcj02_To_Wgs84(item.lat, item.lng);
                        item.lat = info.Latitude;
                        item.lng = info.longitude;
                        break;
                    case GpsMapType.BAIDUMAP:
                        info = gCJ02_WGS84_TransTools.bd09_To_Gps84(item.lat, item.lng);
                        item.lat = info.Latitude;
                        item.lng = info.longitude;
                        break;
                }
            }

            var update = Builders<FenceDto>.Update
                .Set(s => s.UpdateDateTime, DateTime.UtcNow)
                .Set(s => s.UpdateAccountCode, CurrentAccount.AccountCode)
                .Set(s => s.UpdateAccountRole, CurrentAccount.AccountRoleStr)
                .Set(s => s.IsEnable, fenceDto.IsEnable)
                .Set(s => s.FenceAlarmType, fenceDto.FenceAlarmType)
                .Set(s => s.FenceNumber, fenceDto.FenceNumber)
                .Set(s => s.Polygon, fenceDto.Polygon)
                .Set(s => s.Name, fenceDto.Name);

            mongoDBCommand.UpdateDocumentAsync(s => s.Id == fenceDto.Id, update).GetAwaiter().GetResult();
            return mongoDBCommand.SelectDocumentAsync(s=>s.Id == fenceDto.Id).GetAwaiter().GetResult();
        }

        public double Test_GetDistance(double lat1, double lng1, double lat2, double lng2)
        {
            return  GpsMath.GetDistance(lat1, lng1, lat2, lng2);
        }
    }
}

